import basicTypes.C4Constant;
import Prism.core.Architecture;
import Prism.core.Component;
import Prism.core.Connector;
import Prism.core.Port;
import Prism.core.PrismConstants;
import Prism.extensions.port.ExtensiblePort;
import Prism.extensions.port.distribution.SocketDistribution;

import component.BillingSystem;



// Billing Server Program
// This is used for Server version to send data to terminal and collect data from offlinedatabase
// And printBilling Assist to print bills
// And also client version for OfflineDatabase
public class BillingServer {
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {        
		
		// Create Architecture
		Architecture billingSystemArchitecture = new Architecture();
		
		// Create Implementation
		BillingSystem billingSystem = new BillingSystem();
	
        // Create BillingSystem Component
    	Component billingSystemComponent = new Component();
		
		// Create BillingSystem Component's implementation
    	billingSystemComponent.setImplementation(billingSystem);
        
		
	/*
	 * Server Setup
	 */
  
		// Add a port to the BillingSystem for reply requests.
		Port billingSystemReplyPort = new Port(PrismConstants.REPLY);
		billingSystemComponent.addPort(billingSystemReplyPort);
		
		// Add billSystemComponent to billingServerArchitecture
		billingSystemArchitecture.add(billingSystemComponent);
		
		// Create a connector(BillingSystemConn) for BillingSystemUI
		Connector billingSystemConnServer = new Connector();
		
		// Add a port to the BillingSystemConn for forwarding requests.
		Port billingSystemConnRequestPort = new Port(PrismConstants.REQUEST);
		billingSystemConnServer.addPort(billingSystemConnRequestPort);
		
		// BillingSystemConn is extensiblePort because BillSystem and its UI terminal is networked
		ExtensiblePort billingSystemConnReplyPort = new ExtensiblePort (PrismConstants.REPLY);
		billingSystemConnReplyPort.addDistribution(new SocketDistribution(C4Constant.billingPort));           
		billingSystemConnServer.addPort(billingSystemConnReplyPort);
		
        // Add the BillingSystemConn to the billingSystemArchitecture
		billingSystemArchitecture.add(billingSystemConnServer);
		
		// Weld the GUI request port to the connector reply port.
		billingSystemArchitecture.weld(billingSystemReplyPort, billingSystemConnRequestPort);
	
	/*
	 * Client Setup
	 */
		
		// Add a port to the billingSystem for sending requests.
		Port billingSystemRequestPort = new Port(PrismConstants.REQUEST);
		billingSystemComponent.addPort(billingSystemRequestPort);
		
		// Create a connector(offLineDatabaseConn) for billingSystem
		Connector offLineDatabaseConnClient = new Connector();

		// Add a port to the offLineDatabaseConn for receiving requests.
		Port offLineDatabaseConnReplyPort = new Port(PrismConstants.REPLY);
		offLineDatabaseConnClient.addPort(offLineDatabaseConnReplyPort);

		// offLineDatabaseConn is extensiblePort because offLineDatabase connects billingSystem by network
		ExtensiblePort offLineDatabaseConnRequestPort = new ExtensiblePort (PrismConstants.REQUEST);
		offLineDatabaseConnRequestPort.addDistribution(new SocketDistribution());           
		offLineDatabaseConnClient.addPort(offLineDatabaseConnRequestPort);
		
        // Add the offLineDatabaseConn to the billingServerArchitecture
		billingSystemArchitecture.add(offLineDatabaseConnClient);
		
		// Weld the request port to the connector reply port.
		billingSystemArchitecture.weld(billingSystemRequestPort, offLineDatabaseConnReplyPort);
		/* 
		 * Client Ends
		 */
		
		// Start this Architecture
		billingSystemArchitecture.start();

		// Connect the connector request port to the offlineDatabaseConn.
		offLineDatabaseConnRequestPort.connect(C4Constant.hostname, C4Constant.offlineDatabasePort);
		
		// Initial Transaction for test
		billingSystem.getBills();

	}
}
